package com.example.sample;

//import com.alibaba.nacos.api.NacosFactory;
//import com.alibaba.nacos.api.config.ConfigService;
//import com.alibaba.nacos.api.config.listener.Listener;
//import com.alibaba.nacos.api.exception.NacosException;
import com.example.sample.Infrastructure.Thread.TestCallable;
import com.example.sample.Infrastructure.Thread.TestLock;
import com.example.sample.Infrastructure.Thread.TestRunnable;
import com.example.sample.Infrastructure.Thread.TestThread;
import com.example.sample.domain.Entity.Cat;
import com.example.sample.domain.Entity.IAnimal;
import com.example.sample.domain.Entity.Student;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Queue;
import java.util.concurrent.*;
import java.util.concurrent.locks.LockSupport;

@SpringBootApplication
@MapperScan("package com.example.sample.Infrastructure.MybatisPlus")
@EnableDiscoveryClient
public class SampleApplication {

    private volatile int value;

    public static void main(String[] args) {
        SpringApplication.run(SampleApplication.class, args);
    }

    private static void Queue() throws InterruptedException {
        System.out.println("测试add,remove");
        // 添加或者取出超过队列大小的数据时：会抛出异常
        Queue<String> queue = new ArrayBlockingQueue<>(3);
        queue.add("张三");
        queue.add("李四");
        queue.add("王五");
        //queue.add("王五66");
        System.out.println(queue.remove());
        System.out.println(queue.remove());
        System.out.println(queue.remove());
        queue.element();
        //System.out.println(queue.remove());

        System.out.println("测试offer,poll");
        //添加或者取出超过队列大小的数据时：添加会返回 false ，取出返回null
        Queue<String> queue1 = new ArrayBlockingQueue<>(3);
        queue1.offer("张三");
        queue1.offer("李四");
        queue1.offer("王五");
        System.out.println(queue1.poll());
        System.out.println(queue1.poll());
        System.out.println(queue1.poll());
        System.out.println(queue1.poll());
        queue1.peek();

        System.out.println("测试offer,poll 设置超时");
        //添加或者取出超过队列大小的数据时：等待的时间超过设置的超时，添加会返回 false ，取出返回null ,
        ArrayBlockingQueue<String> queue2 = new ArrayBlockingQueue<>(3);
        queue2.offer("张三");
        queue2.offer("李四");
        queue2.offer("王五");
        queue2.offer("张三666", 2, TimeUnit.SECONDS);
        System.out.println(queue2.poll(2, TimeUnit.SECONDS));
        System.out.println(queue2.poll(2, TimeUnit.SECONDS));
        System.out.println(queue2.poll(2, TimeUnit.SECONDS));
        System.out.println(queue2.poll(2, TimeUnit.SECONDS));

        System.out.println("测试put,take");
        //添加或者取出超过队列大小的数据时：一直阻塞
        ArrayBlockingQueue<String> queue3 = new ArrayBlockingQueue<>(3);
        queue3.put("张三");
        queue3.put("李四");
        queue3.put("王五");
        //queue3.put("王五66");
        System.out.println(queue3.take());
        System.out.println(queue3.take());
        System.out.println(queue3.take());
        //System.out.println(queue3.take());
        System.out.println("6666666666666");
    }

//    private static void GetConfig() throws InterruptedException, ExecutionException {
//        ConfigService configService = GetConfigService();
//        Listener listener = new Listener() {
//            @Override
//            public Executor getExecutor() {
//                System.out.println("getExecutor++++++++");
//                return null;
//            }
//
//            @Override
//            public void receiveConfigInfo(String s) {
//
//            }
//        };
//    }
//
//    private static ConfigService GetConfigService() {
//
//        String serverAddr = "1.117.193.193:8848";
//        Properties properties = new Properties();
//        properties.put("serverAddr", serverAddr);
//        ConfigService configService = null;
//        try {
//            configService = NacosFactory.createConfigService(properties);
//        } catch (NacosException e) {
//            e.printStackTrace();
//        }
//        return configService;
//    }

    public static void TestLock() {

        TestLock testLock = new TestLock();
        for (int i = 0; i < 5; i++) {
            new Thread(testLock).start();
        }

        //SpringApplication.run(SampleApplication.class, args);

//        TestLock testLock =new TestLock();
//        new Thread(testLock).start();
//        new Thread(testLock).start();

//        TestCAS cas =new TestCAS();
//        cas.Test();

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("boy: 我要吃鸡");
                LockSupport.park();
                System.out.println("boy: park1");
                System.out.println("boy: park2");
                System.out.println("boy: 开始吃鸡了");
            }
        });

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                LockSupport.unpark(thread); // 第二次会阻塞住，因为只有一个permit
                System.out.println("解锁！");

            }
        });
        thread.start();
        thread1.start();
    }

    public static void TestThread() throws ExecutionException, InterruptedException {

        System.out.println("Thread=============================================");
        TestThread t = new TestThread();
        t.start();

        System.out.println("Runnable=============================================");
        TestRunnable r = new TestRunnable();
        new Thread(r).start();

        System.out.println("Callable=============================================");
        TestCallable callable = new TestCallable("德玛1");
        FutureTask<String> future = new FutureTask<>(callable);
        new Thread(future).start();
        System.out.println(future.get());

        System.out.println("ThreadPool单个返回值=============================================");
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 2, 0, TimeUnit.DAYS,
                new ArrayBlockingQueue<Runnable>(512),
                new ThreadPoolExecutor.DiscardPolicy());
        TestCallable callable1 = new TestCallable("德玛ThreadPool");
        Future<String> futurePool = threadPoolExecutor.submit(callable1);
        String str = futurePool.get();
        System.out.println(str);

        System.out.println("ThreadPool多个返回值=============================================");
        ArrayList<Callable> callableList = new ArrayList<>();
        TestCallable callable2 = new TestCallable("德玛2");
        TestCallable callable3 = new TestCallable("德玛3");
        TestCallable callable4 = new TestCallable("德玛4");
        callableList.add(callable2);
        callableList.add(callable3);
        callableList.add(callable4);
        CompletionService<String> completionService = new ExecutorCompletionService<String>(threadPoolExecutor);// 构造器
        callableList.forEach(e -> {
            completionService.submit(e);
        });

        for (int i = 0; i < callableList.size(); i++) {
            String str1 = completionService.take().get();
            System.out.println(str1);
        }

    }

    public static void TestReflection() throws
            ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //region
        //通过命名空间名称获取Class
        Class clazz = Class.forName("com.example.sample.domain.Entity.Cat");
        //通过类名获取Class
        //clazz = Cat.class;
        //通过对象实例获取Class
        //Cat testCat = new Cat();
        //clazz = testCat.getClass();

        //获取Public的属性
        Field[] fields = clazz.getFields();
        //Field field = clazz.getField("Name");
        //获取当前类中的属性，不包含继承父类的属性
        //fields = clazz.getDeclaredFields();
        //field = clazz.getDeclaredField("Color");
        // 获取字段的类型
        //field.getType().getTypeName()
        //关闭程序的安全检测,使其可以访问和设置私有属性
        //field.setAccessible(true);

        Cat testCatField = new Cat("123", "喵", "红色");
        for (Field field : fields) {
            //获取字段的值
            Object fieldValue = field.get(testCatField);
            System.out.println(field);
            System.out.println(fieldValue);
        }


        //获取类的方法
        Method[] methods = clazz.getMethods();
        methods = clazz.getDeclaredMethods();
        Method method1 = clazz.getMethod("Say");
        System.out.println(method1);
        for (Method method : methods) {
            System.out.println(method);
            Parameter[] paras = method.getParameters();
            for (Parameter para : paras) {
                System.out.println(para);
            }
        }


        //获取构造函数
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            for (Parameter para : constructor.getParameters()) {
                //System.out.println(para.getName());
            }
        }

        //反射调用类
        Object cat1 = (Object) clazz.getDeclaredConstructor().newInstance();
        Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class, String.class, String.class);
        Cat cat = (Cat) declaredConstructor.newInstance("1", "2", "3");
        Method call = clazz.getMethod("TestGr", List.class);
        List<Object> list = new ArrayList<Object>();
        call.invoke(cat1, list);
        Method call22 = clazz.getMethod("TestGr", List.class);
        Type[] genericParameterTypes = call.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            if (genericParameterType instanceof ParameterizedType) {
                for (Type actualTypeArgument : ((ParameterizedType) genericParameterType).getActualTypeArguments()) {
                    System.out.println(actualTypeArgument);
                }

            }
        }
        //endregion

    }

    public static void TestArrayList() {
        List<String> list = new ArrayList();
        list.add("1");
        list.add("2");
        list.add("3");

//        for (int i =0;i<list.toArray().length;i++)
//        {
//            System.out.println(list.toArray()[i]);
//        }
//
//        for (String item:list)
//        {
//            System.out.println(item);
//        }
//
//        Iterator<String> ite=list.iterator();
//        while(ite.hasNext())//判断下一个元素之后有值
//        {
//            System.out.println(ite.next());
//        }

        List<Cat> CatList = new ArrayList<Cat>() {
        };
        Cat cat = new Cat("123", "喵", "红色");
        Cat cat2 = new Cat("456", "狗", "白色");
        CatList.add(cat);
        CatList.add(cat2);

        for (Cat item : CatList) {
            System.out.println(item.Name);
        }


//        Map<String, String> map = new HashMap<String, String>();
//        map.put("123", "小李");
//        map.put("456", "小王");
//        map.put("789", "小张");
//
//        for (String item : map.keySet()) {
//            if (item == "123") {
//                System.out.println("666");
//            } else {
//                System.out.println(item);
//            }
//
//        }
//
//        for (String item : map.values()) {
//
//            System.out.println(item);
//        }

        ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap<String, String>();

        concurrentHashMap.put("123", "小李");
        concurrentHashMap.put("456", "小王");
        concurrentHashMap.put("789", "小张");

        for (String item : concurrentHashMap.values()) {
            System.out.println(item);
        }
        concurrentHashMap.forEach(2, (key, value) -> {
            System.out.println(key);
        });
    }

    public static void TestClass() {
        Cat cat = new Cat("123", "喵", "红色");
        System.out.println(cat.Name);
        cat.Say();
        cat.Sleep();
        System.out.println(IAnimal.num);
    }
}
